package card

import (
	"container/ring"
	"fmt"
	"math/rand"
	"time"
)

const (
	// SuitTong 花色: 筒
	SuitTong = 0
	// SuitTiao 花色: 条
	SuitTiao = 1
	// SuitWan 花色: 万
	SuitWan = 2
	// SuitNone 无花色
	SuitNone = -1
)

const (

	// SuitPointSize 同花色的牌数
	SuitPointSize = 9

	// SuitSize 花色
	SuitSize = 3

	// SameCardSize 同样牌数量
	SameCardSize = 4

	// CardSetSize 总牌数
	CardSetSize = SuitSize * SuitPointSize * SameCardSize
)

// MahjongSet 套牌
type MahjongSet struct {
	// 存放套牌的索引用于: 洗牌，抽牌
	opData *ring.Ring
	// 抽牌位置
	drawPos int
}

var (
	// 组牌(可操作)
	mahjongSet *MahjongSet
)

// GetMahjongSet 获取麻将组牌
func GetMahjongSet() *MahjongSet {
	if mahjongSet != nil {
		mahjongSet.Shuffle()
		return mahjongSet
	}

	rand.Seed(time.Now().Unix())

	mahjongSet = &MahjongSet{ring.New(CardSetSize), 0}
	mahjongSet.Shuffle()
	return mahjongSet
}

// Shuffle 洗牌
func (inst *MahjongSet) Shuffle() {
	var perm []int
	for n := 0; n < SameCardSize; n++ {
		perm = rand.Perm(SuitSize * SuitPointSize)
		for _, v := range perm {
			// fmt.Print(mahjongSetData[v], " ")
			inst.opData.Value = v
			inst.opData = inst.opData.Next()
		}
		inst.drawPos = 0
	}
	// fmt.Println()
}

// GetCardByID 将cardID转换为卡牌
func GetCardByID(cardID int) Card {
	suit := cardID / SuitPointSize
	point := cardID % SuitPointSize
	return Card{suit, point}
}

// GetSuit 将cardID转为花色
func GetSuit(cardID int) int {
	return cardID / SuitPointSize
}

// Draw 抽牌
func (inst *MahjongSet) Draw(count int) []int {
	cards := make([]int, count, count)
	realDrawCount := count
	beyond := inst.drawPos + count - inst.opData.Len()
	if beyond > 0 {
		realDrawCount = count - beyond
	}

	for n := 0; n < realDrawCount; n++ {
		cards[n] = inst.opData.Value.(int)
		inst.opData = inst.opData.Next()
	}

	if beyond > 0 {
		inst.Shuffle()

		for n := 0; n < beyond; n++ {
			cards[n+realDrawCount] = inst.opData.Value.(int)
			inst.opData = inst.opData.Next()
		}
		inst.drawPos = beyond
	} else {
		inst.drawPos = inst.drawPos + count
	}

	return cards
}

func (inst *MahjongSet) Test1() {
	fmt.Printf("count: %v\n", inst.opData.Len())
	for i := 0; i < inst.opData.Len(); i++ {
		// fmt.Printf("%v ", inst.opData.Value)

		fmt.Printf("【%v】\n", GetFriendy(inst.opData.Value.(int)))
		inst.opData = inst.opData.Next()
	}
	println()
}

func Print(cards []int) {
	fmt.Printf("【%v】\n", cards)
	for n := 0; n < len(cards); n++ {
		fmt.Printf("【%v】\n", GetFriendy(cards[n]))

	}
}

func (inst *MahjongSet) Test2() {
	fmt.Printf("第1张牌 %v \n", GetFriendy(inst.opData.Move(-1*inst.drawPos).Value.(int)))
	// fmt.Printf("第一张牌: %v\n", inst.drawPos)
}
